import { Component, ElementRef, ViewChild } from '@angular/core';
import { ICellEditorAngularComp } from '@ag-grid-community/angular';
import { ExpressionService } from '@core/services/expression/ExpressionService';
import { deepClone, getO } from '../../../utils/utils';
import { Events } from '@core/services/events/Events';

export interface InputGroupType {
  group: string, // prefix | suffix
  showType?: string,  // text | icon
  showTextFormatter: string, // 展示文本
  showGroupFormatter?: string,   // 表达式
  showTooltip?: boolean,
  action?: any, // text | button
  callback?: any, // 回调
}

@Component({
  selector: 'apes-cell-input-group',
  template: `
    <apes-input-group
      class="apes-cell-input-group"
      [apesPrefix]="showPrefix? prefixTemplate : null"
      [apesSuffix]="showSuffix? suffixTemplate : null">
      <input apes-input [ngStyle]="{width:'100%'}" #input [placeholder]="placeholder" [(ngModel)]="inputValue"
             (blur)="onBlur()" (keydown)="onKeyDown($event)">
    </apes-input-group>

    <ng-template #prefixTemplate>
      <ng-container *ngTemplateOutlet="commonTemplate;context:{option: prefixOption}"></ng-container>
    </ng-template>

    <ng-template #suffixTemplate>
      <ng-container *ngTemplateOutlet="commonTemplate;context:{option: suffixOption}"></ng-container>
    </ng-template>

    <ng-template #commonTemplate let-option="option">

      <ng-container *ngIf="option['type'] == 'string'">

        <ng-container *ngIf="!option['showFixTooltip']">
          <div>{{option['textFormatter']}}</div>
        </ng-container>

        <ng-container *ngIf="option['showFixTooltip']">
          <div [apes-tooltip]="getFormatter(option['textFormatter'],option['tooltipFormatter'])">
            {{option['textFormatter']}}
          </div>
        </ng-container>

      </ng-container>

      <ng-container *ngIf="option['type'] == 'icon'">

        <ng-container *ngIf="!option['showFixTooltip']">
          <i apes-icon
             class="apes-cell-input-group-icon"
             [ngClass]="{'icon-pointer': option['action'] == 'button'}"
             [apesType]="option['textFormatter']"
             (click)="clickBtn(option)"></i>
        </ng-container>

        <ng-container *ngIf="option['showFixTooltip']">
          <i apes-icon
             class="apes-cell-input-group-icon"
             [ngClass]="{'icon-pointer': option['action'] == 'button'}"
             [apesType]="option['textFormatter']"
             [apes-tooltip]="getFormatter(option['textFormatter'],option['tooltipFormatter'])"
             (click)="clickBtn(option)"></i>
        </ng-container>

      </ng-container>

    </ng-template>
  `,
  styles: [`
    .apes-cell-input-group-icon {
      font-size: 18px;
    }
    .icon-pointer {
      cursor: pointer;
    }
  `],
})
export class EditorInputGroupComponent implements ICellEditorAngularComp {

  placeholder: any = '';
  inputValue: any;
  params: any;
  ctx: any;
  data: any = {};
  rowIndex: any;
  callbackBody: any;
  @ViewChild('input', { static: false }) input: ElementRef;

  showPrefix: boolean = false;
  prefixOption: any = {};
  showSuffix: boolean = false;
  suffixOption: any = {};
  valueFormatter: any;

  // 入参结构
  options: any[] = [
    {
      group: 'prefix', // suffix
      type: 'string',  // icon
      showTextFormatter: '', // 展示文本
      showGroupFormatter: '',   // 表达式
      showTooltip: false,
      action: 'text', // button
      callback: '', // 回调
    },
  ];

  constructor(
    private  expressionService: ExpressionService,
    private event: Events,
    ) {
  }

  agInit(params: any): void {
    this.params = params;
    this.rowIndex = deepClone(this.params.rowIndex);
    this.inputValue = params.value;
    this.ctx = params.context;
    this.data = this.params.data ? this.params.data : this.params.node.data;
    let colDef = params['colDef'] ? params['colDef'] : params.column['colDef'];
    this.initData(colDef);
  }

  initData(colDef) {
    if (colDef.hasOwnProperty('placeholder')) {
      this.placeholder = colDef.placeholder;
    }
    if (colDef.hasOwnProperty('callback')) {
      this.callbackBody = colDef.callback;
    }
    if (colDef.hasOwnProperty('showPrefix')) {
      this.prefixOption = this.initOption(colDef, 'showPrefix');
      this.showPrefix = this.showGroup(this.prefixOption);
    }
    if (colDef.hasOwnProperty('showSuffix')) {
      this.suffixOption = this.initOption(colDef, 'showSuffix');
      this.showSuffix = this.showGroup(this.suffixOption);
    }
    if (colDef.hasOwnProperty('options')) {
      let  options = getO(colDef.options);
      options.forEach((option) => {
        switch (option['group']) {
          case 'prefix':
            this.prefixOption = this.initOption(option, 'showPrefix');
            this.showPrefix = this.showGroup(this.prefixOption);
            break;
          case 'suffix':
            this.suffixOption = this.initOption(option, 'showSuffix');
            this.showSuffix = this.showGroup(this.suffixOption);
            break;
        }
      });
    }
  }

  initOption(params, fix) {
    return {
      group: params['group'] ? params['group'] : fix == 'showPrefix' ? 'prefix' : 'suffix',
      type: params['showType'] ? params['showType'] : 'string',
      textFormatter: params[fix] ? params[fix] : '',
      showGroupFormatter: params['showGroupFormatter'],
      showFixTooltip: !!params['showFixTooltip'],
      tooltipFormatter: params['showFixTooltip'] ? params['showFixTooltip'] : '',
      action: params['action'] ? params['action'] : 'text',
      callback: params['callback'] ? params['callback'] : false,
    };
  }

  showGroup(params){
    let expression = params.showGroupFormatter || 'true';
    return this.expressionService.eval(expression, {
      context: this.ctx,
      model: this.ctx['model'],
      data: this.data,
    });
  }

  extend(data: any) {
    let result = {};
    for (let key in data) {
      let value = data[key];
      if (key === 'context') {
        result['ctx'] = value;
      } else {
        result[key] = value;
      }
    }
    return result;
  }

  ngAfterViewInit() {
    setTimeout(() => {
      this.input.nativeElement.focus();
    }, 300);
  }

  isPopup(): boolean {
    return false;
  }

  getValue(): any {
    let result;
    if (!this.inputValue) {
      result = '';
      this.params.value = '';
    } else {
      result = this.inputValue;
      this.params.value = this.inputValue;
    }
    return result;
  }

  onKeyDown(event): void {
    let key = event.which || event.keyCode;
    if (key === 38 || key === 40) {
      this.preventDefaultAndPropagation(event);
    } else if (key == 13 || key == 9) { // enter
      // in a proper application you'd probably want to inform the user that an input is blank'
      /**/
      this.inputValue = event.target.value;
      this.params.value = event.target.value;
    }
  }

  onBlur(): void {
    if (!this.showSuffix && !this.showPrefix) {
      this.params.stopEditing(false);
    }
  }

  getFormatter(value, formatter) {
    return this.formatter(value, formatter || 'value');
  }

  formatter(value: any, expression: string) {
    return this.expressionService.evaluate(expression, {
      context: this.ctx,
      model: this.ctx['model'],
      data: this.data,
      value: value,
    });
  }

  clickBtn(btn) {
    if (btn.action == 'button') {
      this.openButton(btn);
    }
  }

  openButton(btn) {
    let node = { ...btn, rowIndex: this.rowIndex, event: this.event };

    this.expressionService.evaluate(this.callbackBody, {
      context: this.ctx,
      form: this.ctx['form'],
      model: this.ctx['model'],
      data: this.data,
      node: node,
    }, true);
  }

  private preventDefaultAndPropagation(event) {
    event.preventDefault();
    event.stopPropagation();
  }
}
